package com.kds.smarthome.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.apache.batik.dom.util.DOMUtilities;
import org.apache.batik.util.SVGConstants;
import org.springframework.stereotype.Service;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @author 孔德嵩
 * 创建日期 2024/11/27
 */
@Service
@Slf4j
public class DrawEnergySVGService {
    private static final String SVG_NS = SVGConstants.SVG_NAMESPACE_URI;

    // EER相关常量
    private static final double EER_MIN_VALUE = 0;
    private static final double EER_MAX_VALUE = 7;
    private static final int RULER_MIN_VALUE = 50;
    private static final int RULER_MAX_VALUE = 200;


    private static final Section[] EER_SECTIONS = {
            new Section(0, 2.6, "#FF0000", "不合格"),
            new Section(2.6, 3.5, "#FFA500", "欠缺"),
            new Section(3.5, 4.5, "#FFFF00", "一般"),
            new Section(4.5, 5.5, "#ADFF2F", "良好"),
            new Section(5.5, 7.0, "#008000", "优秀")
    };

    // 能耗标尺相关常量
    private static final EnergyRange[] RULER_SECTIONS = {
            new EnergyRange(50, 70, "优", "#32CD32"),
            new EnergyRange(70, 100, "良", "#ADFF2F"),
            new EnergyRange(100, 150, "中", "#FFD700"),
            new EnergyRange(150, 200, "差", "#FF4500")
    };

    public String generateAvgAreaEnergyRuler(double value, int width, int height) {
        log.debug("Generating ruler SVG with value: {}, width: {}, height: {}", value, width, height);
        try {
            DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
            Document doc = impl.createDocument(SVG_NS, "svg", null);
            Element svgRoot = doc.getDocumentElement();

            // 设置SVG属性
            svgRoot.setAttributeNS(null, "width", String.valueOf(width));
            svgRoot.setAttributeNS(null, "height", String.valueOf(height));

            // 添加字体样式
            addFontStyle(doc, svgRoot);

            int padding = 10;
            int startX = padding;
            int startY = (int) (height * 0.6);
            int rulerWidth = width - (padding * 2);
            int tickHeight = (int) (height * 0.25);
            int majorTickHeight = (int) (tickHeight * 1.3);
            int currentValue = (int) ((value - RULER_MIN_VALUE) / 1.5);

            // 绘制范围段
            drawRulerSections(doc, svgRoot, startX, startY, rulerWidth, tickHeight);

            // 绘制刻度和标签
            drawRulerTicksAndLabels(doc, svgRoot, startX, startY, rulerWidth, tickHeight, majorTickHeight);

            // 绘制动画指针
            drawRulerAnimatedPointer(doc, svgRoot, currentValue, startX, startY, rulerWidth, tickHeight);

            // 转换为字符串
            StringWriter sw = new StringWriter();
            DOMUtilities.writeDocument(doc, sw);
            return Base64.getEncoder().encodeToString(sw.toString().getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new RuntimeException("生成能耗标尺SVG失败", e);
        }
    }

    private void addFontStyle(Document doc, Element svgRoot) {
        Element defs = doc.createElementNS(SVG_NS, "defs");
        Element style = doc.createElementNS(SVG_NS, "style");
        style.setAttributeNS(null, "type", "text/css");
        style.setTextContent("@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap'); " +
                "text { font-family: 'Noto Sans SC', sans-serif; }");
        defs.appendChild(style);
        svgRoot.appendChild(defs);
    }

    private void drawRulerSections(Document doc, Element svgRoot, int startX, int startY, int rulerWidth, int tickHeight) {
        for (EnergyRange range : RULER_SECTIONS) {
            int rangeStart = startX + (int) ((range.min - RULER_MIN_VALUE) / (double)(RULER_MAX_VALUE - RULER_MIN_VALUE) * rulerWidth);
            int rangeWidth = (int) ((range.max - range.min) / (double)(RULER_MAX_VALUE - RULER_MIN_VALUE) * rulerWidth);

            Element rect = doc.createElementNS(SVG_NS, "rect");
            rect.setAttributeNS(null, "x", String.valueOf(rangeStart));
            rect.setAttributeNS(null, "y", String.valueOf(startY - tickHeight));
            rect.setAttributeNS(null, "width", String.valueOf(rangeWidth));
            rect.setAttributeNS(null, "height", String.valueOf(tickHeight));
            rect.setAttributeNS(null, "fill", range.color);
            rect.setAttributeNS(null, "fill-opacity", "0.7");
            svgRoot.appendChild(rect);
        }
    }

    private void drawRulerTicksAndLabels(Document doc, Element svgRoot, int startX, int startY, int rulerWidth, int tickHeight, int majorTickHeight) {
        // 基准线
        Element baseLine = doc.createElementNS(SVG_NS, "path");
        baseLine.setAttributeNS(null, "d", String.format("M%d %d L%d %d", startX, startY, startX + rulerWidth, startY));
        baseLine.setAttributeNS(null, "stroke", "black");
        baseLine.setAttributeNS(null, "stroke-width", "1");
        svgRoot.appendChild(baseLine);

        // 刻度和标签
        for (int v = RULER_MIN_VALUE; v <= RULER_MAX_VALUE; v += 5) {
            int x = startX + (int) ((v - RULER_MIN_VALUE) / (double)(RULER_MAX_VALUE - RULER_MIN_VALUE) * rulerWidth);
            boolean isMajorTick = v % 50 == 0;
            int deltHight=isMajorTick ? majorTickHeight-tickHeight:0;

            Element tick = doc.createElementNS(SVG_NS, "line");
            tick.setAttributeNS(null, "x1", String.valueOf(x));
            tick.setAttributeNS(null, "y1", String.valueOf(startY-tickHeight));
            tick.setAttributeNS(null, "x2", String.valueOf(x));
            tick.setAttributeNS(null, "y2", String.valueOf(startY+deltHight));
            tick.setAttributeNS(null, "stroke", "black");
            tick.setAttributeNS(null, "stroke-width", isMajorTick ? "2" : "1");
            svgRoot.appendChild(tick);

            if (isMajorTick) {
                Element text = doc.createElementNS(SVG_NS, "text");
                text.setAttributeNS(null, "x", String.valueOf(x));
                text.setAttributeNS(null, "y", String.valueOf(startY + 20));
                text.setAttributeNS(null, "text-anchor", "middle");
                text.setAttributeNS(null, "font-size", "10");
                text.setTextContent(String.valueOf(v));
                svgRoot.appendChild(text);
            }
        }
    }

    private void drawRulerAnimatedPointer(Document doc, Element svgRoot, int currentValue, int startX, int startY, int rulerWidth, int tickHeight) {
        int markerX = startX + (int) (currentValue * rulerWidth / 100.0);

        // 创建指针组
        Element defs = doc.createElementNS(SVG_NS, "defs");
        Element markerGroup = doc.createElementNS(SVG_NS, "g");
        markerGroup.setAttributeNS(null, "id", "marker");

        // 三角形指针
        Element pointer = doc.createElementNS(SVG_NS, "path");
        pointer.setAttributeNS(null, "d", String.format("M0 %d L-8 %d L8 %d Z",
                startY - tickHeight - 2,
                startY - tickHeight - 12,
                startY - tickHeight - 12));
        pointer.setAttributeNS(null, "fill", "#0066FF");
        markerGroup.appendChild(pointer);

        // 数值文本
        Element text = doc.createElementNS(SVG_NS, "text");
        text.setAttributeNS(null, "y", String.valueOf(startY - tickHeight - 15));
        text.setAttributeNS(null, "text-anchor", "middle");
        text.setAttributeNS(null, "font-size", "14");
        text.setAttributeNS(null, "font-weight", "bold");
        text.setAttributeNS(null, "fill", "#0066FF");
        text.setTextContent(currentValue + "%");
        markerGroup.appendChild(text);

        defs.appendChild(markerGroup);
        svgRoot.appendChild(defs);

        // 使用指针组并添加动画
        Element use = doc.createElementNS(SVG_NS, "use");
        use.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, "href", "#marker");
        use.setAttributeNS(null, "x", String.valueOf(markerX));

        Element animate = doc.createElementNS(SVG_NS, "animateTransform");
        animate.setAttributeNS(null, "attributeName", "transform");
        animate.setAttributeNS(null, "type", "translate");
        animate.setAttributeNS(null, "from", (startX - markerX) + ",0");
        animate.setAttributeNS(null, "to", "0,0");
        animate.setAttributeNS(null, "dur", "1s");
        animate.setAttributeNS(null, "fill", "freeze");
        animate.setAttributeNS(null, "calcMode", "spline");
        animate.setAttributeNS(null, "keySplines", "0.42 0 0.58 1");
        use.appendChild(animate);

        svgRoot.appendChild(use);
    }


    // EER区间定义类
    private static class Section {
        final double start;
        final double end;
        final String color;
        final String label;

        Section(double start, double end, String color, String label) {
            this.start = start;
            this.end = end;
            this.color = color;
            this.label = label;
        }
    }



    // 能耗范围数据类
    private static class EnergyRange {
        final int min;
        final int max;
        final String level;
        final String color;

        EnergyRange(int min, int max, String level, String color) {
            this.min = min;
            this.max = max;
            this.level = level;
            this.color = color;
        }
    }

    public String generateEERRuler(double eerValue, int width, int height) {
        log.debug("Generating EER SVG with value: {}", eerValue);
        try {
            DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
            Document doc = impl.createDocument(SVG_NS, "svg", null);
            Element svgRoot = doc.getDocumentElement();

            // 设置SVG属性
            svgRoot.setAttributeNS(null, "width", String.valueOf(width));
            svgRoot.setAttributeNS(null, "height", String.valueOf(height));
            svgRoot.setAttributeNS(null, "viewBox", String.format("0 0 %d %d", width, height));

            // 添加字体样式
            addFontStyle(doc, svgRoot);

            // 绘制渐变背景
            int padding = width / 37;  // Approximately 10 for width 375
            int scaleHeight = height / 4;  // Approximately 30 for height 120
            int startY = height / 3;  // Approximately 40 for height 120
            drawEERGradientBackground(doc, svgRoot, padding, scaleHeight, startY, width);

            // 绘制区间
            drawEERSections(doc, svgRoot, padding, scaleHeight, startY, width);

            // 绘制刻度和标签
            drawEERScaleAndLabels(doc, svgRoot, padding, scaleHeight, startY, width);

            // 绘制当前值指针
            drawEERCursor(doc, svgRoot, eerValue, width, height, padding, startY, scaleHeight);

            // 转换为字符串
            StringWriter sw = new StringWriter();
            DOMUtilities.writeDocument(doc, sw);
            return Base64.getEncoder().encodeToString(sw.toString().getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new RuntimeException("生成EER仪表SVG失败", e);
        }
    }

    private void drawEERGradientBackground(Document doc, Element svgRoot, int padding, int scaleHeight, int startY, int width) {
        Element defs = doc.createElementNS(SVG_NS, "defs");
        Element gradient = doc.createElementNS(SVG_NS, "linearGradient");
        gradient.setAttributeNS(null, "id", "eerGradient");
        gradient.setAttributeNS(null, "x1", "0%");
        gradient.setAttributeNS(null, "y1", "0%");
        gradient.setAttributeNS(null, "x2", "100%");
        gradient.setAttributeNS(null, "y2", "0%");

        String[][] stops = {
                {"0%", "#8B0000"},
                {"50%", "#FFFF00"},
                {"100%", "#008000"}
        };

        for (String[] stop : stops) {
            Element stopElement = doc.createElementNS(SVG_NS, "stop");
            stopElement.setAttributeNS(null, "offset", stop[0]);
            stopElement.setAttributeNS(null, "stop-color", stop[1]);
            gradient.appendChild(stopElement);
        }

        defs.appendChild(gradient);
        svgRoot.appendChild(defs);

        // 绘制渐变背景矩形
        Element rect = doc.createElementNS(SVG_NS, "rect");
        rect.setAttributeNS(null, "x", String.valueOf(padding));
        rect.setAttributeNS(null, "y", String.valueOf(startY));
        rect.setAttributeNS(null, "width", String.valueOf(width - 2 * padding));
        rect.setAttributeNS(null, "height", String.valueOf(scaleHeight));
        rect.setAttributeNS(null, "fill", "url(#eerGradient)");
        svgRoot.appendChild(rect);
    }

    private void drawEERSections(Document doc, Element svgRoot, int padding, int scaleHeight, int startY, int width) {
        for (Section section : EER_SECTIONS) {
            double x = padding + (section.start / EER_MAX_VALUE) * (width - 2 * padding);
            double sectionWidth = ((section.end - section.start) / EER_MAX_VALUE) * (width - 2 * padding);
            double midX = x + sectionWidth / 2;

            // 绘制区间矩形
            Element rect = doc.createElementNS(SVG_NS, "rect");
            rect.setAttributeNS(null, "x", String.format("%.1f", x));
            rect.setAttributeNS(null, "y", String.valueOf(startY));
            rect.setAttributeNS(null, "width", String.format("%.1f", sectionWidth));
            rect.setAttributeNS(null, "height", String.valueOf(scaleHeight));
            rect.setAttributeNS(null, "fill", section.color);
            rect.setAttributeNS(null, "fill-opacity", "0.3");
            svgRoot.appendChild(rect);

            // 绘制括号和标签
            int bracketY = startY - 5;
            String bracketPath = String.format(
                    "M%.1f,%d Q%.1f,%d %.1f,%d " +
                            "M%.1f,%d Q%.1f,%d %.1f,%d " +
                            "M%.1f,%d Q%.1f,%d %.1f,%d",
                    x, bracketY, midX, bracketY - 20, x + sectionWidth, bracketY,
                    x, bracketY, x, bracketY + 10, x, bracketY + 5,
                    x + sectionWidth, bracketY, x + sectionWidth, bracketY + 10, x + sectionWidth, bracketY + 5
            );

            Element bracket = doc.createElementNS(SVG_NS, "path");
            bracket.setAttributeNS(null, "d", bracketPath);
            bracket.setAttributeNS(null, "stroke", "grey");
            bracket.setAttributeNS(null, "stroke-width", "1");
            bracket.setAttributeNS(null, "fill", "none");
            svgRoot.appendChild(bracket);

            // 绘制标签
            Element label = doc.createElementNS(SVG_NS, "text");
            label.setAttributeNS(null, "x", String.format("%.1f", midX));
            label.setAttributeNS(null, "y", String.valueOf(bracketY - 15));
            label.setAttributeNS(null, "text-anchor", "middle");
            label.setAttributeNS(null, "font-size", "12");
            label.setAttributeNS(null, "fill", "grey");
            label.setTextContent(section.label);
            svgRoot.appendChild(label);
        }
    }

    private void drawEERScaleAndLabels(Document doc, Element svgRoot, int padding, int scaleHeight, int startY, int width) {
        // 绘制刻度线和数值
        for (double i = 0; i <= EER_MAX_VALUE; i += 0.5) {
            double x = padding + (i / EER_MAX_VALUE) * (width - 2 * padding);
            boolean isMajorTick = Math.abs(i - Math.round(i)) < 0.01;

            Element tick = doc.createElementNS(SVG_NS, "line");
            tick.setAttributeNS(null, "x1", String.format("%.1f", x));
            tick.setAttributeNS(null, "y1", String.valueOf(startY + scaleHeight));
            tick.setAttributeNS(null, "x2", String.format("%.1f", x));
            tick.setAttributeNS(null, "y2", String.valueOf(startY + scaleHeight + (isMajorTick ? 10 : 5)));
            tick.setAttributeNS(null, "stroke", "#000");
            tick.setAttributeNS(null, "stroke-width", isMajorTick ? "2" : "1");
            svgRoot.appendChild(tick);

            if (isMajorTick) {
                Element label = doc.createElementNS(SVG_NS, "text");
                label.setAttributeNS(null, "x", String.format("%.1f", x));
                label.setAttributeNS(null, "y", String.valueOf(startY + scaleHeight + 20));
                label.setAttributeNS(null, "text-anchor", "middle");
                label.setAttributeNS(null, "font-size", "10");
                label.setTextContent(String.format("%.1f", i));
                svgRoot.appendChild(label);
            }
        }
    }

    private void drawEERCursor(Document doc, Element svgRoot, double eerValue, int width, int height, int padding, int startY, int scaleHeight) {
        double cursorX = padding + (eerValue / EER_MAX_VALUE) * (width - 2 * padding);

        // 创建指针组
        Element cursorGroup = doc.createElementNS(SVG_NS, "g");
        cursorGroup.setAttributeNS(null, "id", "cursor");

        // 绘制外部白线
        Element outerLine = doc.createElementNS(SVG_NS, "line");
        outerLine.setAttributeNS(null, "x1", String.valueOf(cursorX));
        outerLine.setAttributeNS(null, "y1", String.valueOf(startY));
        outerLine.setAttributeNS(null, "x2", String.valueOf(cursorX));
        outerLine.setAttributeNS(null, "y2", String.valueOf(startY + scaleHeight));
        outerLine.setAttributeNS(null, "stroke", "white");
        outerLine.setAttributeNS(null, "stroke-width", "4");
        outerLine.setAttributeNS(null, "stroke-linecap", "round");
        cursorGroup.appendChild(outerLine);

        // 绘制内部红线
        Element innerLine = doc.createElementNS(SVG_NS, "line");
        innerLine.setAttributeNS(null, "x1", String.valueOf(cursorX));
        innerLine.setAttributeNS(null, "y1", String.valueOf(startY));
        innerLine.setAttributeNS(null, "x2", String.valueOf(cursorX));
        innerLine.setAttributeNS(null, "y2", String.valueOf(startY + scaleHeight));
        innerLine.setAttributeNS(null, "stroke", "red");
        innerLine.setAttributeNS(null, "stroke-width", "1");
        cursorGroup.appendChild(innerLine);

        // 绘制上下三角形
        String upperTrianglePath = String.format(
                "M%.1f,%d L%.1f,%d L%.1f,%d Z",
                cursorX, startY,
                cursorX + 10, startY - 10,
                cursorX - 10, startY - 10
        );
        Element upperTriangle = doc.createElementNS(SVG_NS, "path");
        upperTriangle.setAttributeNS(null, "d", upperTrianglePath);
        upperTriangle.setAttributeNS(null, "fill", "red");
        upperTriangle.setAttributeNS(null, "stroke", "white");
        upperTriangle.setAttributeNS(null, "stroke-width", "2");
        cursorGroup.appendChild(upperTriangle);

        String lowerTrianglePath = String.format(
                "M%.1f,%d L%.1f,%d L%.1f,%d Z",
                cursorX, startY + scaleHeight,
                cursorX + 10, startY + scaleHeight + 10,
                cursorX - 10, startY + scaleHeight + 10
        );
        Element lowerTriangle = doc.createElementNS(SVG_NS, "path");
        lowerTriangle.setAttributeNS(null, "d", lowerTrianglePath);
        lowerTriangle.setAttributeNS(null, "fill", "red");
        lowerTriangle.setAttributeNS(null, "stroke", "white");
        lowerTriangle.setAttributeNS(null, "stroke-width", "2");
        cursorGroup.appendChild(lowerTriangle);

        // 添加指针动画
        Element cursorAnimate = doc.createElementNS(SVG_NS, "animateTransform");
        cursorAnimate.setAttributeNS(null, "attributeName", "transform");
        cursorAnimate.setAttributeNS(null, "type", "translate");
        cursorAnimate.setAttributeNS(null, "from", padding - cursorX + ",0");
        cursorAnimate.setAttributeNS(null, "to", "0,0");
        cursorAnimate.setAttributeNS(null, "dur", "1s");
        cursorAnimate.setAttributeNS(null, "fill", "freeze");
        cursorAnimate.setAttributeNS(null, "calcMode", "spline");
        cursorAnimate.setAttributeNS(null, "keySplines", "0.42 0 0.58 1");
        cursorGroup.appendChild(cursorAnimate);

        // 设置指针组的初始位置
        cursorGroup.setAttributeNS(null, "transform", "translate(" + cursorX + ",0)");
        svgRoot.appendChild(cursorGroup);

        // 创建单独的文本标签组
        Element textGroup = doc.createElementNS(SVG_NS, "g");

        // 获取当前等级
        String currentLevel = "";
        for (Section section : EER_SECTIONS) {
            if (eerValue >= section.start && eerValue < section.end) {
                currentLevel = section.label;
                break;
            }
        }

        // 添加文本标签
        Element valueLabel = doc.createElementNS(SVG_NS, "text");
        valueLabel.setAttributeNS(null, "x", "0");  // 使用相对坐标
        valueLabel.setAttributeNS(null, "y", String.valueOf(startY + scaleHeight + 35));
        valueLabel.setAttributeNS(null, "text-anchor", "middle");
        valueLabel.setAttributeNS(null, "font-size", "14");
        valueLabel.setAttributeNS(null, "font-weight", "bold");
        valueLabel.setAttributeNS(null, "fill", "#0066FF");
        valueLabel.setTextContent(String.format("%s: %.1f", currentLevel, eerValue));
        textGroup.appendChild(valueLabel);

        // 设置文本组的初始位置和动画
        textGroup.setAttributeNS(null, "transform", "translate(" + cursorX + ",0)");
        Element textAnimate = doc.createElementNS(SVG_NS, "animateTransform");
        textAnimate.setAttributeNS(null, "attributeName", "transform");
        textAnimate.setAttributeNS(null, "type", "translate");
        textAnimate.setAttributeNS(null, "from", padding + ",0");  // 从左侧开始
        textAnimate.setAttributeNS(null, "to", cursorX + ",0");   // 移动到指针位置
        textAnimate.setAttributeNS(null, "dur", "1s");
        textAnimate.setAttributeNS(null, "fill", "freeze");
        textAnimate.setAttributeNS(null, "calcMode", "spline");
        textAnimate.setAttributeNS(null, "keySplines", "0.42 0 0.58 1");
        textGroup.appendChild(textAnimate);

        svgRoot.appendChild(textGroup);
    }
}

